//Lecture 2: Histogram Equalizar
package test;
import java.applet.*; 
import java.awt.*;
import java.awt.image.*;

public class equalizer extends Applet 
{ 
	Choice imagenes = new Choice();	
	Button load;		
	Button aplicar;	

	Image img;
	int weight = 284;
	int height = 129;
	int[] pixels;
	int pixel;
	PixelGrabber m_pixelgrabber;

//	Original Histogram
	int[] histogram = new int[256];
	int maxFrequency = 0;
	int maxFrequencyIndx = 1;
	
//Equalized Histogram
	int[] histogram_eq=new int[256];
	int maxFrequency_eq = 0;
	int maxFrequencyIndx_eq = 1;

	double area;

	double cumNormHist[]=new double [256];
	double min;
	int[] dest=new int[256];
	int destino;
	int[] pixelsdestino;
	Image m_ImageNew;
	boolean ecualizar = false;


	public void init()
	{
		load = new Button ("Load selected image"); 

		imagenes.addItem("Legs");
		imagenes.addItem("Lake");
		imagenes.addItem("Pedobear");
		imagenes.addItem("Barragan");
        
		add(imagenes);
		add(load);

		aplicar = new Button ("Equalize image");
		add(aplicar);

		for (int i = 0 ; i < 256 ; i ++) 
			histogram[i] = 0;

		maxFrequencyIndx = 1 ;
		maxFrequency = 1 ;

		for (int i = 0 ; i < 256 ; i ++)
			histogram_eq[i] = 0;

		maxFrequencyIndx_eq = 1;
		maxFrequency_eq = 1;

	} 

	public boolean action ( Event e, Object o ) 
	{ 
		String parametro;
		int indice;

		if ( e.target == load ) 
		{
			indice=imagenes.getSelectedIndex();
	
			if(indice==0)
				img=getImage(getDocumentBase(), "image000.jpg" );
				else if(indice==1)
							img=getImage(getDocumentBase(), "image001.jpg" );
							else if(indice==2)
										img=getImage(getDocumentBase(), "image002.jpg" );
										else img=getImage(getDocumentBase(), "image003.jpg" );
			ecualizar=false;	
	 		repaint();
    	 	return true; 
		} 

		if ( e.target == aplicar )
		{ 
			pixels = new int[weight * height];
			m_pixelgrabber = new PixelGrabber (img, 0, 0, weight, height, pixels, 0, weight) ;
			try {
				m_pixelgrabber.grabPixels();
			}
			catch (InterruptedException e2) {
				System.err.println("interrupted waiting for pixels!");
			}

			for (int i = 0 ; i < 256 ; i ++)
				histogram[i] = 0;
	
			for (int r = 0 ; r < height ; r++) {
	        	for (int c = 0 ; c < weight ; c++) 
				{
					pixel = pixels[r * weight  + c] & 0xff;
					histogram [pixel]++;
				}
			}

			maxFrequencyIndx=0;
			maxFrequency=0;

			for (int i = 0 ; i < 256 ; i++) {
				if (histogram[i] > maxFrequency) 
				{
					maxFrequencyIndx = i ;
					maxFrequency = histogram[i] ;
				}
			}

			area = weight * height ;

			for (int i = 0 ; i < 256 ; i++)
				cumNormHist [i] = 0 ;
    
			cumNormHist[0] = (double)histogram[0]/area;

			if (cumNormHist[0]!=0)
				min=cumNormHist[0];
			else min=1;

			for (int i = 1 ; i < 256 ; i++) 
			{
				cumNormHist[i] = cumNormHist[i - 1] + ((double)histogram[i]/area);
				if ((cumNormHist[i]!=0) & (cumNormHist[i]<min))
					min=cumNormHist[i];
			}

			pixelsdestino=new int[weight*height];
			for (int i = 0 ; i < 256 ; i++)
				dest [i] =(int) (((cumNormHist[i]-min)/(1-min))*255 + 0.5);

			for (int r = 0 ; r < height ; r++) {
		        for (int c = 0 ; c < weight ; c++) 
				  {
					  	pixel = pixels[r * weight  + c] & 0xff;
						destino = dest[pixel];
						int origen = destino;
						int suma = 0;
						int[] b = new int[33] ;
						for (int i = 1 ; i < 9 ; i ++) 
						{
							b[i] = origen % 2;
							if (b[i]==1)
								b[i]=0;
							else	b[i]=1;
							b[i]=b[i] & 1;
							b[i+8] = b[i];
							b[i+16] = b[i];
							b[i+24]= 0;
							origen = origen / 2;
						}
	
						for (int j = 1 ; j <= 24 ; j ++)
							suma=suma+(b[j]*(int)(Math.pow(2,(double)(j-1))));
			
						suma=suma+1;
						suma=0-suma;
	
						pixelsdestino[r * weight + c]= suma;
					}
			}	

			MemoryImageSource mis = new MemoryImageSource(weight, height, pixelsdestino, 0, weight) ;
			m_ImageNew = createImage (mis) ;

			for (int i = 0 ; i < 256 ; i ++) 
				histogram_eq[i] = 0;

			for (int r = 0 ; r < height ; r++) {
	        	for (int c = 0 ; c < weight ; c++) 
				{
					pixel = pixelsdestino[r * weight  + c] & 0xff;
					histogram_eq [pixel]++;
				}
			}

			maxFrequencyIndx_eq=0;
			maxFrequency_eq=0;

			for (int i = 0 ; i < 256 ; i++) {
				if (histogram_eq[i] > maxFrequency_eq) 
				{
					maxFrequencyIndx_eq = i ;
					maxFrequency_eq = histogram_eq[i] ;
				}
			}

			ecualizar=true;
			repaint();
	      return true; 
		} 
		return false; 
	}

   public void paint(Graphics g) 
	{
		g.drawString("HISTOGRAM EQUALIZATION",10,25);

		g.drawLine(0,40,700,40);
		g.drawLine(205,0,205,40);
		g.drawString("ORIGINAL IMAGE",20,60);
		g.drawString("EQUALIZED IMAGE",375,60);

		g.drawLine(0,67,700,67);
		g.drawLine(350,40,350,425);
	
		g.drawLine(0,230,700,230);
	
		g.drawString("HISTOGRAM FROM ORIGINAL IMAGE",20,250);
		g.drawString("HISTOGRAM FROM EQUALIZED IMAGE",375,250);
	
		g.drawLine(0,257,700,257);
	
	
		g.drawImage(img,33,84,this);

		if (ecualizar) 
		{
			g.drawImage(m_ImageNew,383,84,this);

			int offset=15;

			int desplaza=33;
			int baja=275;

			g.setColor (new Color (255, 255, 255)) ;
			g.fillRect(desplaza+0, baja+0, 255 + offset * 2  - 1, 100 + offset * 2 - 1) ;

			g.setColor (new Color (0, 0, 0)) ;
			g.drawRect(desplaza+0, baja+0, 255 + offset * 2, 100 + offset * 2) ;

			g.setColor (new Color (0, 0, 0)) ;
			g.drawString ("0", desplaza+offset / 2, baja+100 + offset * 2 - 2) ;
			g.drawString ("255", desplaza+255, baja+100 + offset * 2 - 2) ;
			g.drawString (String.valueOf(maxFrequency), desplaza+2, baja+offset) ;

			for (int i = 0 ; i < 256 ; i++)
			        g.drawLine (desplaza+i + offset, baja+100 + offset - ((int)(((float)histogram[i] / (float)maxFrequency_eq) * 100.0)), desplaza+i  + offset, baja+100  + offset);


			int desplaza2=383;
			int baja2=275;

			g.setColor (new Color (255, 255, 255)) ;
			g.fillRect(desplaza2+0, baja2+0, 255 + offset * 2  - 1, 100 + offset * 2 - 1) ;

			g.setColor (new Color (0, 0, 0)) ;
			g.drawRect(desplaza2+0, baja2+0, 255 + offset * 2, 100 + offset * 2) ;

			g.setColor (new Color (0, 0, 0)) ;
			g.drawString ("0", desplaza2+offset / 2, baja2+100 + offset * 2 - 2) ;
			g.drawString ("255", desplaza2+255, baja2+100 + offset * 2 - 2) ;
			g.drawString (String.valueOf(maxFrequency_eq), desplaza2+2, baja2+offset) ;

			for (int i = 0 ; i < 256 ; i++)
			        g.drawLine (desplaza2+i + offset, baja2+100 + offset - ((int)(((float)histogram_eq[i] / (float)maxFrequency_eq) * 100.0)), desplaza2+i  + offset, baja2+100  + offset);
		}
	}
}